<template>
  <div class="item">
    <a-row type="flex" align="middle">
      <a-col :xs="7" :sm="7" :md="7" :lg="7" style="padding-right: 5px">
        <a-cascader
          :options="propertyData"
          v-model="dimensionVal"
          expand-trigger="hover"
          :show-search="{ propertyFilter }"
          @change="changeProperty"
          :allow-clear="true"
          placeholder="请选择属性"
          :disabled="disabled"
        ></a-cascader>
      </a-col>
      <a-col :xs="6" :sm="6" :md="6" :lg="6" style="padding-right: 5px">
        <a-select @change="changeOperator" v-model="rule.operator" :disabled="disabled">
          <a-select-option v-for="item in operatorList" :value="item.name" :key="item.name">{{ item.displayName }}
          </a-select-option>
        </a-select>
      </a-col>
      <a-col v-if="valueType !== ''" :xs="6" :sm="6" :md="6" :lg="6" style="padding-right: 5px">
        <a-select v-if="valueType === 'select'"
            :disabled="disabled"
                  v-model="rule.values"
                  mode="tags"
                  @search="onSearch"
                  :loading="loading"
                  option-filter-prop="children"
                  :filter-option="filterOption"
                  @dropdownVisibleChange="onOpenChange">
          <a-select-option v-for="(item, index) in valueList" :value="item.value" :key="item.value+'-'+index">
            {{ item.displayName }}
          </a-select-option>
        </a-select>
        <a-input :disabled="disabled" v-if="valueType === 'input'" v-model="rule.value" placeholder=""/>
      </a-col>
      <a-col :xs="5" :sm="5" :md="5" :lg="5" style="padding-right: 5px">
        <!-- <a-button v-show="group" @click="addGroup">并且满足</a-button> -->
        <a-button v-if="!disabled" icon="minus" style="margin-left: 3px;" @click="remove"></a-button>
        <!-- <a-button icon="plus" style="margin-left: 3px;" v-if="index === 0" @click="add"></a-button> -->
      </a-col>
    </a-row>
  </div>
</template>

<script>
import {compareObject} from "@/components/CompareUtils";
import {debounce} from "@/components/OptimizeUtils";
import {mapActions} from 'vuex';

const numberOperators = [
  {
    name: 'equal',
    displayName: '等于',
    valueType: 'input'
  },
  {
    name: 'notEqual',
    displayName: '不等于',
    valueType: 'input'
  },
  {
    name: 'greater',
    displayName: '大于'
  },
  {
    name: 'greaterOrEqual',
    displayName: '大于等于'
  },
  {
    name: 'less',
    displayName: '小于'
  },
  {
    name: 'lessOrEqual',
    displayName: '小于等于'
  },
  {
    name: 'isSet',
    displayName: '有值'
  },
  {
    name: 'isNotSet',
    displayName: '无值'
  }
];
const stringOperators = [
  {
    name: 'equal',
    displayName: '等于'
  },
  {
    name: 'notEqual',
    displayName: '不等于'
  },
  {
    name: 'contain',
    displayName: '包含'
  },
  {
    name: 'notContain',
    displayName: '不包含'
  },
  {
    name: 'isSet',
    displayName: '有值'
  },
  {
    name: 'isNotSet',
    displayName: '无值'
  }
];
const booleanOperators = [
  {
    name: 'isTrue',
    displayName: '为真'
  },
  {
    name: 'isFalse',
    displayName: '为假'
  },
  {
    name: 'isSet',
    displayName: '有值'
  },
  {
    name: 'isNotSet',
    displayName: '无值'
  }
];
export default {
  name: "Rule",
  props: {
    value: Object,
    properties: Array,
    datasourceId: {
      type: Number,
      default: null
    },
    index: Number,
    virtual: {
      type: Boolean,
      default: false
    },
    group: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
  },
  data() {
    return {
      dimensionVal:[],
      rule: this.value,
      valueList: [],
      loading: false
    }
  },
  computed: {
    propertyData() {
      const data = []
      const ep = this.buildEventProperties()
      const up = this.buildUserProperties()
      const ug = this.buildUserGroupProperties()
      const ut = this.buildUserTagProperties()
      if (ep) {
        data.push(ep)
      }
      if (up) {
        data.push(up)
      }
      if (ug) {
        data.push(ug)
      }
      if (ut) {
        data.push(ut)
      }
      return data
    },
    //根据属性的数据类型，更改操作符下拉选项的内容
    operatorList: function () {
      if (this.propertyType === 'number') {
        return numberOperators;
      } else if (this.propertyType === 'string') {
        return stringOperators;
      } else if (this.propertyType === 'boolean') {
        return booleanOperators;
      }
    },
    //获取属性的数据类型
    propertyType: function () {
      for (let i = 0; i < this.properties.length; i++) {
        if (this.properties[i].name === this.rule.property) {
          return this.properties[i].type;
        }
      }
      return 'number';
    },
    //根据属性数据类型和操作符，决定值部分是显示输入框还是下拉选择框。
    valueType: function () {
      if (this.propertyType === "boolean") {
        return "";
      } else if (this.propertyType === "string") {
        if (this.rule.operator.search("is") !== -1) {
          return "";
        } else if (this.rule.operator === "contain" || this.rule.operator === "notContain") {
          return "input";
        }
        return "select";
      } else if (this.propertyType === "number") {
        if (this.rule.operator.search("is") !== -1) {
          return "";
        }
        return "input";
      }
      return "input";
    },
    eventProperties: function () {
      return this.properties.filter((item) => {
        return item.name.indexOf("events.") === 0 || (this.virtual && item.name.indexOf("virtual.events.") === 0)
      });
    },
    userProperties: function () {
      return this.properties.filter((item) => {
        return this.isUserProperty(item.name)
      });
    },
    userGroups: function () {
      return this.properties.filter((item) => {
        return item.name.indexOf("users.cg_") === 0
      });
    },
    userTags: function () {
      return this.properties.filter((item) => {
        return item.name.indexOf("users.ut_") === 0
      });
    }
  },
  methods: {
    ...mapActions('analyseType', ['getEventValuesByProjectId', 'getUserValuesByProjectId']),
    isUserProperty(val){
      return (val.indexOf("users.") === 0 || (this.virtual && val.indexOf("virtual.users.") === 0))
        && val.indexOf("users.cg_") !== 0
        && val.indexOf("users.ut_") !== 0
    },
    buildEventProperties() {
      const data = []
      let gd = {}
      for (let i in this.eventProperties) {
        if (typeof this.eventProperties[i].group === "string") {
          const group = this.eventProperties[i].group
          if (typeof gd[group] === "undefined") {
            gd[group] = []
          }
          gd[group].push(this.eventProperties[i])
        }
      }
      for (let i in gd) {
        const children = []
        for (let j in gd[i]) {
          children.push({
            value: gd[i][j].name,
            label: gd[i][j].displayName
          })
        }
        data.push({
          value: i,
          label: i,
          children: children
        })
      }
      if (data.length > 0) {
        return {value: '事件属性', label: '事件属性', children: data}
      } else {
        return null
      }
    },
    buildUserProperties() {
      const userProperties = this.userProperties
      const children = []
      for (let i in userProperties) {
        children.push({
          value: userProperties[i].name,
          label: userProperties[i].displayName
        })
      }
      if (children.length > 0) {
        return {value: '用户属性', label: '用户属性', children: children}
      } else {
        return null
      }
    },
    buildUserGroupProperties() {
      const properties = this.userGroups
      const children = []
      for (let i in properties) {
        children.push({
          value: properties[i].name,
          label: properties[i].displayName
        })
      }
      if (children.length > 0) {
        return {value: '用户分群', label: '用户分群', children: children}
      } else {
        return null
      }

    },
    buildUserTagProperties() {
      const result = []
      let categories = {}
      const dataList = this.userTags
      dataList.map(item => {
        const category = item.categoryName
        if (typeof category === 'string') {
          if (categories[category]) {
            categories[category].children.push({
              value: item.name,
              label: item.displayName
            })
          } else {
            categories[category] = {
              value: category,
              label: category,
              children: [{value: item.name, label: item.displayName}]
            }
          }
        }
      })
      for (let i in categories) {
        result.push(categories[i])
      }
      if (result.length > 0) {
        return {value: '用户标签', label: '用户标签', children: result}
      } else {
        return null
      }
    },
    checkPropertyType (name){
      if (name.indexOf("events.") === 0 || (name.indexOf("virtual.events.") === 0)){
        return "event"
      }else if (this.isUserProperty(name)){
        return "user"
      }else if (name.indexOf("users.cg_") === 0){
        return "userGroup"
      }else if (name.indexOf("users.ut_") === 0){
        return "userTag"
      }else return null
    },
    onDimensionChanged(){
      if (typeof this.rule.property !== "string"){
        return []
      }
      const name = this.rule.property
      if (this.checkPropertyType(name) === 'event'){
        let group = ""
        for (let i in this.eventProperties){
          if (this.eventProperties[i].name === name){
            group = this.eventProperties[i].group
            break
          }
        }
        this.dimensionVal = ['事件属性', group, name]
      }else if (this.checkPropertyType(name) === 'user'){
        this.dimensionVal = ['用户属性', name]
      }else if (this.checkPropertyType(name) === 'userGroup'){
        this.dimensionVal = ['用户分群', name]
      }else if (this.checkPropertyType(name) === 'userTag'){
        let group = ""
        for (let i in this.userTags){
          if (this.userTags[i].name === name){
            group = this.userTags[i].categoryName
            break
          }
        }
        this.dimensionVal = ['用户标签', group, name]
      }
    },
    propertyFilter(inputValue, path) {
      return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
    },
    filterOption(input, option) {
      return (
        option.componentOptions.children.length > 0
        && option.componentOptions.children[0].text
        && option.componentOptions.children[0].text.indexOf(input) > -1
      );
    },
    //根据value初始化data中的rule
    initRule(value) {
      this.rule.property = value.property;
      this.rule.operator = value.operator;
      this.rule.values = value.values;
      this.rule.value = value.value;
    },
    initValueList() {
      if (this.rule.property) {
        this.onDimensionChanged();
      }
      //初始化多选下拉选框可选项列表，否则多选下拉框无法显示
      this.rule.values.map((item, index) => {
        this.valueList.push({
          displayName: item,
          value: item
        });
      });
    },
    changeOperator() {
      this.rule.value = "";
      this.rule.values.splice(0, this.rule.values.length);
      this.valueList.splice(0, this.valueList.length);
    },
    changeProperty: function (value) {
      if (!value || value.length === 0){
        this.rule.property = null
      }else {
        this.rule.property = value[value.length - 1]
      }
      this.rule.operator = this.operatorList[0].name;
      this.rule.value = "";
      this.rule.values.splice(0, this.rule.values.length);
      this.valueList.splice(0, this.valueList.length);
      this.rule.type = this.propertyType;

      // this.rule.operator = this.operatorList[0].name;
      // this.rule.value = "";
      // this.rule.values.splice(0, this.rule.values.length);
      // this.valueList.splice(0, this.valueList.length);
    },
    //根据关键词获取属性值列表
    getPropertyValues: function (keyword) {
      if (this.propertyType === "string") {
        let type = "";
        let propertyName = "";
        let tokens = this.rule.property.split(".");
        if (tokens.length === 3 && tokens[0] === 'virtual') {
          //处理虚拟属性名
          type = tokens[1].slice(0, -1);
          propertyName = tokens[2];
        } else if (tokens.length === 2) {
          //处理正常属性名
          type = tokens[0].slice(0, -1);
          propertyName = tokens[1];
        } else {
          return;
        }
        if (type == 'event') {
          let res = null
          res = this.getEventValuesByProjectId({projectId: this.datasourceId, propertyName, keyword})
          res.then(response => {
            this.valueList.splice(0, this.valueList.length);
            //限制值的长度不超过50，超出显示省略号，避免显示不友好
            response.data.forEach((item, index) => {
              if (item.displayName.length > 50) {
                item.displayName = item.displayName.substr(0, 50) + "...";
              }
              this.valueList.push(item);
            });
          }).catch(error => {
            console.error(error);
          }).finally(() => {
            //如果values在valueList中不存在，则需要将values中的值添加到valueList中，否则多选框无法显示values。
            let values = [];
            this.valueList.map((item, index) => {
              values.push(item.value);
            });
            this.rule.values.map((item, index) => {
              if (values.indexOf(item) === -1) {
                this.valueList.push({
                  displayName: item,
                  value: item
                });
              }
            });
            this.loading = false;
          });
        } else if (type == 'user') {
          let res = null
          res = this.getUserValuesByProjectId({projectId: this.datasourceId, propertyName, keyword})
          res.then(response => {
            this.valueList.splice(0, this.valueList.length);
            //限制值的长度不超过50，超出显示省略号，避免显示不友好
            response.data.forEach((item, index) => {
              if (item.displayName.length > 50) {
                item.displayName = item.displayName.substr(0, 50) + "...";
              }
              this.valueList.push(item);
            });
          }).catch(error => {
            console.error(error);
          }).finally(() => {
            //如果values在valueList中不存在，则需要将values中的值添加到valueList中，否则多选框无法显示values。
            let values = [];
            this.valueList.map((item, index) => {
              values.push(item.value);
            });
            this.rule.values.map((item, index) => {
              if (values.indexOf(item) === -1) {
                this.valueList.push({
                  displayName: item,
                  value: item
                });
              }
            });

            this.loading = false;
          });
        }
      }
    },
    //下拉选框展开时，查询属性值
    onOpenChange: function (state) {
      if (state) {
        this.loading = true;
        let query = debounce(this.getPropertyValues, 1000);
        query("");
      }
    },
    //远程搜索
    onSearch: function (keyword) {
      this.loading = true;
      let query = debounce(this.getPropertyValues, 1000);
      query(keyword);
    },
    //删除当前条件
    remove: function () {
      this.$emit("remove", this.index);
    },
    //追加新条件
    add: function () {
      this.$emit("add");
    },
    //增加新条件，与当前条件形成条件组
    addGroup: function () {
      this.$emit("add-group", this.index);
    }
  },
  watch: {
    rule: {
      handler(newVal, oldVal) {
        this.$emit("input", newVal)
      },
      deep: true
    },
    value: {
      handler(newVal, oldVal) {
        if (!compareObject(newVal, this.rule)) {
          this.initRule(newVal);
        }
      },
      deep: true
    },
    properties(newVal) {
      if (typeof newVal === 'object' && newVal.length > 0){
        this.onDimensionChanged()
      }
    }
  },
  mounted() {
    this.initValueList();
  }
}
</script>

<style scoped>
.item {
  padding: 5px 0px;
}
</style>
